package com.example.demo.web.ztree;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.example.demo.bean.Menu;
import com.example.demo.bean.MenuStream;
import com.example.demo.bean.Menus;
import com.example.demo.web.SysBaseController;
import com.fasterxml.jackson.annotation.JsonInclude;

import lombok.extern.slf4j.Slf4j;

/**
 * @ClassName MenuController
 * @Description 尚筹网|menu感觉不过，学习一下|sql文件位置 file/menu.sql
 * @Author 51
 * @Date 2020年3月17日 上午9:32:52
 */
@SuppressWarnings({ "unchecked", "rawtypes", "unused" })
@Slf4j
@Controller
@RequestMapping("/menu")
public class MenuController extends SysBaseController {
	@Resource
	JdbcTemplate jdbcTemplate;

	/**
	 * 菜单首页
	 * 
	 * @return
	 */
	@RequestMapping("/index")
	public String index(Model model) {
		return "menu/menu";
	}

	@RequestMapping("/indexstream")
	public String indexjava8stream(Model model) {
		return "menu/menu2";
	}

	@RequestMapping("/allnew")
	@ResponseBody
	public Object getMenu() {
		log.info("menu");
		// 只支持Integer.class String.class
		// 这种单数据类型的，自己定义的Bean不支|https://blog.csdn.net/J_mani/article/details/83896372?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
		// List<Menu> queryForList = jdbcTemplate.queryForList("select * from t_menu",
		// Menu.class);
		List<Menu> queryForList = jdbcTemplate.query("select id,pId ,name,url,icon from t_menu", new BeanPropertyRowMapper(Menu.class));
		System.out.println("AdminController.getALL()");
		log.info(queryForList.toString());
		return queryForList;
	}

	private <E> List<E> getAllmenu(Class<E> clazz) {
		return jdbcTemplate.query("select id,pId ,name,url,icon from t_menu", new BeanPropertyRowMapper(clazz.getClass()));
	}

	/**
	 * getWholeTreeOld 和getWholeTreeNew|后者使用了 map这样来遍历查询，去map中的key，比前者方便
	 * 
	 * @return
	 */

	@RequestMapping("/all_new")
	@ResponseBody
	public Object getWholeTreeNew() {

		// 1.查询全部的Menu对象
		List<Menus> menuList = jdbcTemplate.query("select id,pid ,name,url,icon from t_menu", new BeanPropertyRowMapper(Menus.class));

		// 2.声明一个变量用来存储找到的根节点
		Menus root = null;

		// 3.创建Map对象用来存储id和Menu对象的对应关系便于查找父节点
		Map<Integer, Menus> menuMap = new HashMap<>();

		// 4.遍历menuList填充menuMap
		for (Menus menu : menuList) {
			Integer id = menu.getId();
			menuMap.put(id, menu);
		}

		// 5.再次遍历menuList查找根节点、组装父子节点
		for (Menus menu : menuList) {

			// 6.获取当前menu对象的pid属性值
			Integer pid = menu.getPid();

			// 7.如果pid为null，判定为根节点
			if (pid == null) {
				root = menu;

				// 8.如果当前节点是根节点，那么肯定没有父节点，不必继续执行
				continue;
			}

			// 9.如果pid不为null，说明当前节点有父节点，那么可以根据pid到menuMap中查找对应的Menu对象
			Menus father = menuMap.get(pid);

			// 10.将当前节点存入父节点的children集合
			father.getChildren().add(menu);
		}
		return root;
	}

	@RequestMapping("/all")
	@ResponseBody
	public Object getWholeTreeOld() {
		// 1.查询全部的Menu对象
		List<Menus> menuList = jdbcTemplate.query("select id,pid ,name,url,icon from t_menu", new BeanPropertyRowMapper(Menus.class));
		// 2.声明一个变量用来存储找到的根节点
		Menus root = null;
		// 3.遍历menuList
		for (Menus menu : menuList) {
			// 4.获取当前menu对象的pid属性值
			Integer pid = menu.getPid();
			// 5.检查pid是否为null
			if (pid == null) {
				// 6.把当前正在遍历的这个menu对象赋值给root
				root = menu;
				// 7.停止本次循环，继续执行下一次循环
				continue;
			}
			// 8.如果pid不为null，说明当前节点有父节点，找到父节点就可以进行组装，建立父子关系
			for (Menus maybeFather : menuList) {
				// 9.获取maybeFather的id属性
				Integer id = maybeFather.getId();
				// 10.将子节点的pid和疑似父节点的id进行比较
				if (Objects.equals(pid, id)) {
					// 11.将子节点存入父节点的children集合
					maybeFather.getChildren().add(menu);
					// 12.找到即可停止运行循环
					break;
				}

			}
		}
		log.info(root.toString());
		// 13.将组装的树形结构（也就是根节点对象）返回给浏览器
		return root;
	}

	/**
	 * 使用java8 stream封装父子节点 关系
	 */

	@RequestMapping("/java8stream")
	@ResponseBody
	public Object java8stream() {
		log.info("menu with java8stream");
		// 使用java8 stream 封装父子关系，来展示 ztree 标准JSON格式
		List<MenuStream> queryForList = jdbcTemplate.query("select id,pId ,name,url,icon from t_menu", new BeanPropertyRowMapper(MenuStream.class));

		// 获取取根节点
		List<MenuStream> collect = queryForList.stream().filter((menu) -> {
			return menu.getPid() == null;
		}).map((menu) -> {
			menu.setChildren(getChildren(menu, queryForList));
			return menu;
		}).sorted((m1, m2) -> {
			return m1.getId() - m2.getId();
		}).collect(Collectors.toList());

		System.out.println();
		System.out.println(collect);
		return collect;
	}

	/**
	 * 查找所有节点子节点
	 * 
	 * @param root
	 * @param all
	 * @return
	 */
	private List<MenuStream> getChildren(MenuStream root, List<MenuStream> all) {

		List<MenuStream> collect = all.stream().filter(menu -> {
			// 根据父节点查找子节点
			return menu.getPid() == root.getId();
		}).map(menuStream -> {
			// 递归设置 子节点
			List<MenuStream> children = getChildren(menuStream, all);
			menuStream.setChildren(children);
			if (children != null && !children.isEmpty()) {
				// @JsonInclude(JsonInclude.Include.NON_EMPTY) // 设置不为空的时候返回
				// private List<MenuStream> children;
			}
			return menuStream;
		}).collect(Collectors.toList());
		return collect;
	}
}
